﻿using System;

namespace 虚方法和隐藏方法
{
    class Program
    {
        static void Main(string[] args)
        {
            /*虚方法和隐藏方法的不同
              虚方法在基类指针指向派生类对象的时候依然可以调用自身方法也可以调用基类方法
              隐藏方法不能调用自身方法和父类方法
              虚方法基类指针指向派生类对象的时候先调用本身方法在调用基类方法。
              而隐藏方法什么也不会调用，即使继承了基类，
             */
            AA a = new BB();
            AA b = new CC();
            CC c = new CC();
            BB d = new BB();

            a.get();
            b.get();
            Console.WriteLine("------------");
            c.get();
            d.get();
        }
    }
    // 虚方法：virtual  关键字修饰的一个方法
    // virtual ： 虚拟的，虚构的，不真实的
    // 用于标记一个方法不真实，别人封装的方法里面的内容固化的，但virtual 修饰的却是虚晃一枪后面可以反悔的。
    // 隐藏方法： new ，新 ，新建
    // override 修饰的方法，可以从上往下调（类似于功能的
    // new 修饰的方法，可以从上往下调用（类似于功能的补充）补充），也可以从基类唤起 （out ref）
    class AA
    {
        
        /*虚方法是实现多态的方法之一还有接口，抽象类
          将父类的方法标记为虚方法，使用关键字virtual，
          这个函数可以被子类重新写一遍。
          在父类方法返回值前面写上关键字virtual，
          然后在子类方法返回值前面写上override
         */
        public virtual void get()//虚方法
        {
            Console.WriteLine("a在吃饭呢！");
        }
    }
    class BB:AA//虚方法必须是由基类方法标记虚方法，然后由派生类来进行重写。
    {
        // override ：覆写，用于替换(隐藏)/补充 虚方法内的逻辑
        public override void get()//override重写，用来重写用virtual标记的虚方法
        {
            // base.get() 是调用 基类中的 get 逻辑
            //如果是替换逻辑，这句话干掉，不执行 Walk
            // 如果是补充方法的逻辑，这句话不能干掉，而且还可以随意穿插在你的逻辑中
            //base.get();//base 用来调用父类的get方法
            Console.WriteLine("B在吃饭呢");
        }
    }
    class CC : AA
    {
        public new void get()//子类方法和父类方法重名IDE会提示使用new关键字来进行隐藏方法
        {
            base.get();//将父类方法隐藏也可以在方法内部进行调用
            Console.WriteLine("C在吃饭呢");
        }
    }
}
